<?php
// La idea era grabar en la session un Ext_Model_User row pero el problema es que se 
// graba mucho mas de lo deseado, por eso cree esta clase.
class Ext_Auth_AuthenticatedUser
{
    public $id;

    public $user_id;

    public $username;

    public $applicationId;

    public $locked;

    public $end_date;

    public $ownerId;

    public $creationDate;

    public $properties;

    public $acl;

    public function __construct( $user, $applicationId = null )
    {
        $this->user_id = $user->user_id;
        $this->username = $user->username;
        $this->password = null;
        $this->locked = $user->locked;
        $this->end_date = $user->end_date;

        $this->applicationId = $applicationId;


        // For compatibility
        $this->id = $user->user_id;
        $this->creationDate = $user->creation_date;

        // For backward compatibility.
        if ( isset( $user->owner_id ) ) {
            $this->ownerId = $user->owner_id;
        } else if ( isset( $user->customer_id ) ) {
            $this->ownerId = $user->customer_id;
        } else {
            $this->ownerId = null;
        }

        // add properties to user obeject if any
        $this->properties = array();
        foreach ( $user->findExt_Model_UserProperty() as $prop ) {
            $this->properties[ $prop->property ] = $prop->value;
        }
        $this->loadAcl( $user );
    }

    public function __get( $columnName )
    {
        if ( $this->properties !== null && isset( $this->properties[ $columnName ] ) ) {
            return $this->properties[ $columnName ];
        }
        return null;
    }

    public function __set( $columnName, $value )
    {
        $this->properties[ $columnName ] = $value;
        // Si esta clase esta siendo usada por Zend_Auth grabo.
        $auth = Zend_Auth::getInstance();
        if ( $auth->hasIdentity() && get_class( $auth->getIdentity() ) == get_class( $this ) ) {
            $auth->getStorage()->write( $this );
        }
    }

    public function saveProperties( $db )
    {
        $userPropertyDb = new Ext_Model_UserProperty( $db );
        foreach ( $this->properties as $name => $value ) {
            $userProperty = $userPropertyDb->find( $this->user_id, $name )->current();
            if ( empty( $userProperty ) ) {
                $userProperty = $userPropertyDb->createRow();
                $userProperty->user_id = $this->user_id;
                $userProperty->property = $name;
            }
            $userProperty->value = $value;
            $userProperty->save();
        }
    }

    private function loadAcl( $user )
    {
        $this->acl = new Zend_Acl( );
        $resourceDb = new Ext_Model_Resource( $user->getTable()->getAdapter() );
        /*if(  $this->applicationId != null ){
            $resources = $resourceDb->fetchAll( 'application_id = ' . $this->applicationId );
        } else {*/
        $resources = $resourceDb->fetchAll();
        //}

        foreach ( $resources as $resource ) {
            $this->acl->add( new Zend_Acl_Resource( $this->getResourceName($resource->name, $resource->application_id ) ) );
        }
        $userRoles = $user->findManyToManyRowset( 'Ext_Model_Role', 'Ext_Model_UserRole' );

        $userRoleIds = array();
        foreach ( $userRoles as $role ) {
            $this->acl->addRole( new Zend_Acl_Role( $role->role_id ), $role->parent_role_id );

            $query = $user->getTable()->getAdapter()->select()
            ->from( array('a' => 'sys_acl_rule' ), array('*')  )
            ->join( array( 'b' => 'sys_resource' ), 'a.resource_id = b.resource_id', array('b.name') )
            ->where( 'a.role_id = ?', $role->role_id );
            /*if(  $this->applicationId != null ){
                $query->where( 'b.application_id = ?', $this->applicationId  );
            }*/

            $permsRS = $user->getTable()->getAdapter()->fetchAll( $query->order( 'priority' ) );

            /*$resModel = new Ext_Model_Resource();*/
            foreach ( $permsRS as $perm ) {
                if ( strtoupper( $perm[ 'permission' ] ) === "ALLOW" ) {
                    try{
                        $this->acl->allow( $role->role_id
                            , $this->getResourceName($perm[ 'name' ], $resourceDb->find( $perm[ 'resource_id' ])->current()->application_id )
                            , $perm[ 'operation' ] );
                    }catch (Exception $e ) {}
                } else {
                    $this->acl->deny( $role->role_id
                        , $this->getResourceName($perm[ 'name' ], $resourceDb->find( $perm[ 'resource_id' ])->current()->application_id  )
                        , $perm[ 'operation' ] );
                }
            }

            $userRoleIds[] = $role->role_id;
        }
        $this->acl->addRole( new Zend_Acl_Role( $user->username ), $userRoleIds );
    }

    public function isAllowed( $resource, $privilege, $applicationId = null )
    {
        try {
            return $this->acl->isAllowed( $this->username
                , $this->getResourceName($resource, $applicationId)
                , $privilege );
        } catch( Exception $e ) {}
        return false;
    }

    private function getResourceName( $resourceName, $applicationId = null) {
        //echo (( $applicationId != null ) ?  $applicationId : $this->applicationId )  . "_" . $resourceName;
        return (( $applicationId != null ) ?  $applicationId : $this->applicationId )  . "_" . $resourceName;
    }
}
